{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import os\n",
    "import matplotlib.pyplot as plt\n",
    "import pickle\n",
    "\n",
    "import tensorflow as tf\n",
    "\n",
    "from tensorflow.keras import layers\n",
    "from tensorflow.keras.preprocessing import image, sequence\n",
    "from tensorflow.keras.applications import VGG16\n",
    "from tensorflow.keras.layers import Input, Dense, Convolution2D, Dropout, LSTM, SimpleRNN,TimeDistributed, Embedding, Bidirectional, Activation, RepeatVector, concatenate, Concatenate\n",
    "from tensorflow.keras.models import Sequential, Model\n",
    "from tensorflow.keras.optimizers import Nadam, RMSprop\n",
    "\n",
    "from tensorflow.lite.experimental.examples.lstm.rnn import bidirectional_dynamic_rnn\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(5, 5, 1)\n"
     ]
    }
   ],
   "source": [
    "input_train = [[[0],[0],[1],[2],[3]],[[2],[3],[4],[5],[6]],[[3],[4],[5],[6],[7]],[[4],[5],[6],[7],[8]],[[5],[6],[7],[8],[9]]]\n",
    "output_train = [4,7,8,9,10]\n",
    "\n",
    "input_train1 = [[[1]]]\n",
    "output_train1=[1]\n",
    "\n",
    "input_np1 = np.array(input_train1)\n",
    "output_np1 = np.array(output_train1)\n",
    "\n",
    "input_np = np.array(input_train)\n",
    "output_np = np.array(output_train)\n",
    "\n",
    "input_train = input_np.reshape(input_np.shape[0],5,input_np.shape[2])\n",
    "output_train = output_np.reshape(output_np.shape[0],1,)\n",
    "\n",
    "print(input_train.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"sequential_11\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "dense_21 (Dense)             (None, 5, 20)             40        \n",
      "_________________________________________________________________\n",
      "lstm_9 (LSTM)                (None, 128)               76288     \n",
      "_________________________________________________________________\n",
      "dense_22 (Dense)             (None, 11)                1419      \n",
      "_________________________________________________________________\n",
      "activation_11 (Activation)   (None, 11)                0         \n",
      "=================================================================\n",
      "Total params: 77,747\n",
      "Trainable params: 77,747\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n",
      "Training started\n",
      "Training completed\n"
     ]
    }
   ],
   "source": [
    "#tf.reset_default_graph()\n",
    "\n",
    "model = Sequential()\n",
    "\n",
    "model.add(Dense(20, input_shape=(input_train.shape[1], input_train.shape[2])))\n",
    "\n",
    "model.add(LSTM(units=128, input_shape=(input_train.shape[1],20), activation=\"relu\"))\n",
    "\n",
    "model.add(Dense(11))\n",
    "model.add(Activation('softmax'))\n",
    "\n",
    "model.compile(loss='sparse_categorical_crossentropy', optimizer=RMSprop(), metrics=['accuracy'])\n",
    "\n",
    "model.summary()\n",
    "\n",
    "print(\"Training started\")\n",
    "\n",
    "model.fit(input_np, output_np, batch_size=2, epochs=100, verbose=False)\n",
    "\n",
    "print(\"Training completed\")\n",
    "\n",
    "model.save_weights(\"./new_lstm.h5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "327484"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### convert language model to tflite\n",
    "\n",
    "converter = tf.lite.TFLiteConverter.from_keras_model(model)\n",
    "\n",
    "# THIS FLAG NEED TO BE SET WITH EXPERIMENTAL API \n",
    "# LSTM using keras(tensorflow v2) cannot be converted directly but using experimental api we can convert them\n",
    "\n",
    "converter.experimental_new_converter = True \n",
    "\n",
    "converter.target_ops = [tf.lite.OpsSet.TFLITE_BUILTINS,\n",
    "                        tf.lite.OpsSet.SELECT_TF_OPS]\n",
    "\n",
    "tflite_model = converter.convert()\n",
    "\n",
    "open(\"lstm_new.tflite\", \"wb\").write(tflite_model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "input tensor:\n",
      "[[[1.]\n",
      "  [2.]\n",
      "  [3.]\n",
      "  [4.]\n",
      "  [5.]]]\n",
      "output tensor:\n",
      "[[3.7963314e-06 6.2080153e-06 4.8009720e-06 8.3769019e-06 2.7630993e-04\n",
      "  1.3812809e-05 1.6654143e-06 9.3425483e-01 6.0052492e-02 5.2406546e-03\n",
      "  1.3714554e-04]]\n",
      "\n",
      "prediction : 7\n"
     ]
    }
   ],
   "source": [
    "### doing inference of tflite model\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "# Load TFLite model and allocate tensors.\n",
    "interpreter = tf.lite.Interpreter(model_path=\"lstm_new.tflite\")\n",
    "interpreter.allocate_tensors()\n",
    "\n",
    "# Get input and output tensors.\n",
    "input_details = interpreter.get_input_details()\n",
    "output_details = interpreter.get_output_details()\n",
    "\n",
    "\n",
    "input_data = np.array([[[1],[2],[3],[4],[5]]], dtype=np.float32)\n",
    "\n",
    "print(\"input tensor:\")\n",
    "print(input_data)\n",
    "\n",
    "interpreter.set_tensor(input_details[0]['index'], input_data)\n",
    "\n",
    "interpreter.invoke()\n",
    "\n",
    "# The function `get_tensor()` returns a copy of the tensor data.\n",
    "# Use `tensor()` in order to get a pointer to the tensor.\n",
    "\n",
    "output_data = interpreter.get_tensor(output_details[0]['index'])\n",
    "print(\"output tensor:\")\n",
    "print(output_data)\n",
    "\n",
    "print(\"\\nprediction : \"+str(np.argmax(output_data)) )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
